// b05.v
// Verilog version, rewritten by Li Shen, Aug 2002
// Institute of Computing Technology, Chinese Academy of Sciences
// The original VHDL version is b05.vhd from Politecnico di Torino

module b05(CLOCK,RESET,START,SIGN,DISPMAX1,DISPMAX2,DISPMAX3,DISPNUM1,DISPNUM2);
input CLOCK;
input RESET;
input START;
output SIGN;
output [6:0] DISPMAX1,DISPMAX2,DISPMAX3;
output [6:0] DISPNUM1,DISPNUM2;
/////
wire CLOCK;
wire RESET;
wire START;
reg SIGN;
reg [6:0] DISPMAX1,DISPMAX2,DISPMAX3;
reg [6:0] DISPNUM1,DISPNUM2;
/////
parameter st0=0, st1=1, st2=2, st3=3, st4=4;
reg [4:0] NUM, MAR;
reg [8:0] TEMP, MAX; //signed
reg FLAG, MAG1, MAG2, MIN1;
reg EN_DISP, RES_DISP;
/////
function [8:0] MEM; //signed
input [4:0] addr;
begin
  case (addr)
    0:  MEM=50;  1:  MEM=40;  2:  MEM=0;   3:  MEM=229;
    4:  MEM=502;/*-10*/ 5:  MEM=75;  6:  MEM=229; 7:  MEM=181;
    8:  MEM=186; 9:  MEM=229; 10: MEM=186; 11: MEM=501;/*-11*/
    12: MEM=0;   13: MEM=40;  14: MEM=50;  15: MEM=483;/*-29*/
    16: MEM=494;/*-18*/ 17: MEM=229; 18: MEM=229; 19: MEM=151;
    20: MEM=229; 21: MEM=100; 22: MEM=125; 23: MEM=10;
    24: MEM=75;  25: MEM=462;/*-50*/ 26: MEM=0;   27: MEM=490;/*-22*/
    28: MEM=0;   29: MEM=40;  30: MEM=50;  31: MEM=50;
  endcase
end
endfunction
/////
reg [9:0] AC1, AC2; //signed
reg [8:0] AC; //signed

always @(MAR or TEMP or MAX) 
begin
  AC = MEM(MAR);
  AC1 = {AC[8],AC}-{TEMP[8],TEMP};  
  if (AC1[9]) //<0
  begin
    MIN1 <= 1;
    MAG1 <= 0;
  end
  else
  begin
    if (!AC1)
    begin
      MIN1 <= 0;
      MAG1 <= 0;
    end
    else
    begin
      MIN1 <= 0;
      MAG1 <= 1;
    end
  end
  AC2 = {AC[8],AC}-{MAX[8],MAX};
  if (AC2[9]) //<0
    MAG2 <= 1;
  else
    MAG2 <= 0;
end
/////
reg [8:0] TM, TN; //signed

always @(EN_DISP or RES_DISP or NUM or MAX)                     
begin
  if (EN_DISP)
  begin
    DISPMAX1 <= 7'b0000000;
    DISPMAX2 <= 7'b0000000;
    DISPMAX3 <= 7'b0000000;
    DISPNUM1 <= 7'b0000000;
    DISPNUM2 <= 7'b0000000;
    SIGN <= 0;
  end
  else
  begin
    if (!RES_DISP)
    begin
      DISPMAX1 <= 7'b1000000;
      DISPMAX2 <= 7'b1000000;
      DISPMAX3 <= 7'b1000000;
      DISPNUM1 <= 7'b1000000;
      DISPNUM2 <= 7'b1000000;
      SIGN <= 1;
    end
    else
    begin
      TN = NUM;
      if (MAX[8]) //<0
      begin
        SIGN <= 1;
        TM = -MAX & 31;
      end
      else
      begin
        SIGN <= 0;
        TM = MAX & 31;
      end

      if (TM > 99)
      begin
        DISPMAX1 <= 7'b0011000;
        TM = TM - 100;
      end
      else
        DISPMAX1 <= 7'b0111111;

      if (TM > 89)
      begin
        DISPMAX2 <= 7'b1111110;
        TM = TM - 90;
      end
      else if (TM > 79)
           begin
             DISPMAX2 <= 7'b1111111;
             TM = TM - 80;
           end
      else if (TM > 69)
           begin
             DISPMAX2 <= 7'b0011100;
             TM = TM - 70;
           end
      else if (TM > 59)
           begin
             DISPMAX2 <= 7'b1110111;
             TM = TM - 60;
           end
      else if (TM > 49)
           begin
             DISPMAX2 <= 7'b1110110;
             TM = TM - 50;
           end
      else if (TM > 39)
           begin
             DISPMAX2 <= 7'b1011010;
             TM = TM - 40;
           end
      else if (TM > 29)
           begin
             DISPMAX2 <= 7'b1111001;
            TM = TM - 30;
           end
      else if (TM > 19)
           begin
             DISPMAX2 <= 7'b1101100;
             TM = TM - 20;
           end
      else if (TM > 9)
           begin
             DISPMAX2 <= 7'b0011000;
             TM = TM - 10;
           end
      else
        DISPMAX2 = 7'b0111111;

      if      (TM > 8) DISPMAX3 <= 7'b1111110;
      else if (TM > 7) DISPMAX3 <= 7'b1111111;
      else if (TM > 6) DISPMAX3 <= 7'b0011100;
      else if (TM > 5) DISPMAX3 <= 7'b1110111;
      else if (TM > 4) DISPMAX3 <= 7'b1110110;
      else if (TM > 3) DISPMAX3 <= 7'b1011010;
      else if (TM > 2) DISPMAX3 <= 7'b1111001;
      else if (TM > 1) DISPMAX3 <= 7'b1101100;
      else if (TM > 0) DISPMAX3 <= 7'b0011000;
      else             DISPMAX3 <= 7'b0111111;

      if (TN > 9)
      begin
        DISPNUM1 <= 7'b0011000;
        TN = TN - 10;
      end
      else
        DISPNUM1 <= 7'b0111111;

      if      (TN > 8) DISPNUM2 <= 7'b1111110;
      else if (TN > 7) DISPNUM2 <= 7'b1111111;
      else if (TN > 6) DISPNUM2 <= 7'b0011100;
      else if (TN > 5) DISPNUM2 <= 7'b1110111;
      else if (TN > 4) DISPNUM2 <= 7'b1110110;
      else if (TN > 3) DISPNUM2 <= 7'b1011010;
      else if (TN > 2) DISPNUM2 <= 7'b1111001;
      else if (TN > 1) DISPNUM2 <= 7'b1101100;
      else if (TN > 0) DISPNUM2 <= 7'b0011000;
      else             DISPNUM2 <= 7'b0111111;
    end
  end
end
/////
reg [2:0] STATO;
reg [5:0] TMN;

always @(posedge CLOCK)
begin
  if (RESET)
  begin
    STATO = st0;
    RES_DISP <= 0;
    EN_DISP <= 0;
    NUM <= 0;
    MAR <= 0;
    TEMP <= 0;
    MAX <= 0;
    FLAG <= 0;
  end
  else
    case (STATO)
    st0: begin
           RES_DISP <= 0;
           EN_DISP <= 0;
           STATO = st1;
         end
    st1: begin
           if (START)
           begin
             NUM <= 0;
             MAR <= 0;
             FLAG <= 0;
             EN_DISP <= 1;
             RES_DISP <= 1;
             STATO = st2;
           end
           else
             STATO = st1;
         end
    st2: begin
           MAX <= MEM(MAR);
           TEMP <= MEM(MAR);
           STATO = st3;
         end
    st3: begin
           if (MIN1)
           begin
             if (FLAG)
             begin
               FLAG <= 0;
               NUM <= NUM+1;
             end
           end
           else
             if (MAG1)
             begin
               if (MAG2) MAX <= MEM(MAR);
               FLAG <= 1;
             end
           TEMP <= MEM(MAR);
           STATO = st4;
         end
    st4: begin
           if (MAR == 31)
           begin
             if (START)
               STATO = st4;
             else
               STATO = st1;
             EN_DISP <= 0;
           end
           else
           begin
             MAR <= MAR+1;
             STATO = st3;
           end
         end
    endcase
end
endmodule
